package ru.spb.osll.myfit.wikiverifier.iterator;

import java.io.IOException;
import java.net.URLClassLoader;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.Table;
import ru.spb.osll.myfit.common.TableStyle;
import ru.spb.osll.myfit.server.MyFitClassLoaderFactory;
import ru.spb.osll.myfit.server.fixtureiterator.FileFactory;
import ru.spb.osll.myfit.server.handler.PageLoader;
import ru.spb.osll.myfit.server.parser.TableElementParser;
import ru.spb.osll.myfit.server.parser.TableUtils;
import ru.spb.osll.myfit.server.templateloader.JarTableTemplateLoader;
import ru.spb.osll.myfit.server.templateloader.TableTemplateLoader;
import ru.spb.osll.myfit.wikiverifier.WikiVerifier;
import ru.spb.osll.myfit.wikiverifier.result.AggregatedVerificationResult;
import ru.spb.osll.myfit.wikiverifier.result.PageVerificationResult;
import ru.spb.osll.myfit.wikiverifier.resulthandler.AggregatedVerificationResultHandler;
import ru.spb.osll.myfit.wikiverifier.resulthandler.PageVerificationResultHandler;

public class WikiVerifierFSIteratorListener implements
    FileSystemIteratorListener {
  private JarTableTemplateLoader m_templateLoader;
  private WikiVerifier m_verifier;
  private PageLoader m_pageLoader;
  private List<PageVerificationResultHandler> m_pageResultHandlers;
  private List<AggregatedVerificationResultHandler> m_aggregatedResultHandlers;
  private AggregatedVerificationResult m_aggregatedResult;
  private String m_verificatonPath;

  public WikiVerifierFSIteratorListener(String jarPath, String verificatonPath) {
    URLClassLoader classLoader = new MyFitClassLoaderFactory(new FileFactory())
        .createClassLoader(jarPath, jarPath);
    m_templateLoader = new JarTableTemplateLoader(jarPath, classLoader);
    m_verifier = new WikiVerifier(getTemplates(m_templateLoader),
        m_templateLoader.getFixtureClasses());
    m_verificatonPath = verificatonPath;
    m_pageLoader = new PageLoader(new TableUtils(
        m_templateLoader.getFixtureClasses()));
    m_pageResultHandlers = new LinkedList<PageVerificationResultHandler>();
    m_aggregatedResultHandlers = new LinkedList<AggregatedVerificationResultHandler>();
    m_aggregatedResult = new AggregatedVerificationResult();
    m_pageResultHandlers.add(m_aggregatedResult);
  }

  public void addResultHandler(PageVerificationResultHandler handler) {
    m_pageResultHandlers.add(handler);
  }

  public void addResultHandler(AggregatedVerificationResultHandler handler) {
    m_aggregatedResultHandlers.add(handler);
  }

  @Override
  public void listen(String fileName) {
    try {
      Page page = m_pageLoader.loadPage(fileName);
      PageVerificationResult result = m_verifier.verifyPage(page, true);
      handleResult(fileName, result);
    } catch (IOException e) {
    }
  }

  @Override
  public void handleFinish() {
    for (AggregatedVerificationResultHandler handler : m_aggregatedResultHandlers) {
      handler.handleResult(m_verificatonPath, m_aggregatedResult);
    }
  }

  private void handleResult(String pagePath, PageVerificationResult result) {
    for (PageVerificationResultHandler handler : m_pageResultHandlers) {
      handler.handleResult(pagePath, result);
    }
  }

  private List<Table> getTemplates(TableTemplateLoader templateLoader) {
    LinkedList<Table> templates = new LinkedList<Table>();
    TableElementParser parser = new TableElementParser();

    for (Class< ? > clazz : templateLoader.getFixtureClasses().values()) {
      Vector<String> rawTable = templateLoader.getTemplate(clazz.getName());
      Table template = parser.parseTable(rawTable);
      TableStyle templateTableStyle = TableUtils.getTableStyle(clazz);
      if (template.getData().size() > 0) {
        template.setStyle(templateTableStyle);
        templates.add(template);
      }
    }

    return templates;
  }
}
